//------------------------------------------------------------------------------
// X2TK Graphic Toolkit
// Copyright (C) 2006-2008 Janusz Kowalski
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#include "x2tk_Screen.h"

#include "global.h"

#include "imgSDL.h"

#include "x2tk.h"

#ifdef X2D_WITH_OPENGL
#include "GL/gl.h"
#include "GL/glu.h"
#endif

#include "pmsg.h"

namespace x2tk {

Screen::Screen(SDL_Surface *screen)
    : Container(0,0,screen->w,screen->h), hasFocus_(true)
{
  this->screen=screen;
  pointerX=0;
  pointerY=0;
  mousePtr = Image(X2D_PATH_DATA "arrow.png");
  SDL_ShowCursor(SDL_DISABLE);
  font=new Font(X2D_PATH_DATA "HiTechFont_Black.png");
  fontLight = new Font(X2D_PATH_DATA "HiTechFont_White.png");
}

void Screen::handleSDLEvent(SDL_Event &event) {
  switch(event.type) {
    case SDL_ACTIVEEVENT:
      if(event.active.state & SDL_APPINPUTFOCUS) {
        if(event.active.gain) hasFocus_=true;
        else hasFocus_=false;
        
        // Fire events.
        Widget *fowner = this;
        while(!!fowner && !fowner->fEvFocus_) {
          fowner->fEvFocus_=true;
          pushEvent(fowner, EV_FOCUS);
          fowner=fowner->getFocusOwner();
        }
      }
      break;
    case SDL_VIDEORESIZE:
      resize(event.resize.w, event.resize.h);
      break;
    case SDL_KEYDOWN:
      event_key(event.key);
      break;
    case SDL_KEYUP:
      event_key(event.key);
      break;
    case SDL_MOUSEMOTION:
      mouseMove(event.motion.x,event.motion.y);
      break;
    case SDL_MOUSEBUTTONDOWN:
      switch(event.button.button) {
        case SDL_BUTTON_LEFT:
          mouseDown(1);
          break;
        case SDL_BUTTON_RIGHT:
          mouseDown(2);
          break;
        case SDL_BUTTON_MIDDLE:
          mouseDown(3);
          break;
        case 5:
          mouseDown(5);
          break;
        case 4:
          mouseDown(4);
          break;
      };
      break;
    case SDL_MOUSEBUTTONUP:
      switch(event.button.button) {
        case SDL_BUTTON_LEFT:
          mouseUp(1); break;
        case SDL_BUTTON_RIGHT:
          mouseUp(2); break;
        case SDL_BUTTON_MIDDLE:
          mouseUp(3); break;
        case 4:
          mouseUp(4); break;
        case 5:
          mouseUp(5); break;
      }
      break;
    default:
      break;
  }
}

void Screen::blitSurface(SDL_Surface *src, int x0, int y0, int x, int y, int w, int h) {
  SDL_Rect rect;
  rect.x=x; rect.y=y; rect.w=w; rect.h=h;
  SDL_SetClipRect(screen, &rect);
  SDL_Rect dst={x0,y0,0,0};
  SDL_BlitSurface(src, 0, screen, &dst);
  SDL_SetClipRect(screen, 0);
}

void Screen::blitSurface(SDL_Surface *src, int dstX, int dstY) {
  if(screen!=0) {
    SDL_Rect dstRect;
    dstRect.x=dstX; dstRect.y=dstY;
    SDL_BlitSurface(src, 0, screen, &dstRect); 
  }
}

void Screen::fillRectangle(int x, int y, int w, int h, int r, int g, int b) {
  if(screen!=0) {
    SDL_Rect dstRect;
    dstRect.x=x; dstRect.y=y; dstRect.w=w; dstRect.h=h;
    Uint32 color=SDL_MapRGB(screen->format, r, g, b);
    SDL_FillRect(screen, &dstRect, color);
  }
}

void Screen::draw() {
#ifdef X2D_WITH_OPENGL
  glClear(GL_COLOR_BUFFER_BIT);
#endif
  // Create graphic context.
  GraphicContext g(screen);
  // Draw the background
  if((screen->flags & SDL_OPENGL) == 0) SDL_FillRect(screen, 0, 0);
  // Draw function from the parent class
  Container::draw(g);
  
  // Draw mouse pointer.
  g.blitImage(mousePtr, pointerX, pointerY);
  
  // Flip'nij ekran
  // !! We should check if OpenGL is actually in use.
#ifdef X2D_WITH_OPENGL
  glFlush();
  SDL_GL_SwapBuffers();
#else
  SDL_Flip(screen);
#endif
}

void Screen::mouseMove(int x, int y) {
  // Zrób to, co robi szanujący się Containter
  Container::mouseMove(x,y);
  // Oraz zapamiętaj pozycję wskaźnika, by można było o nią zapytać
  pointerX=x; pointerY=y;
}

short Screen::getMouseX() {
  return pointerX;
}

short Screen::getMouseY() {
  return pointerY;
}

int Screen::textWidth(const char *text) {
  return font->w(text);
}

void Screen::timed(int id) {
  // Move focus owner to the top.
  if(getFocusOwner()!=0) getFocusOwner()->toTheTop();
};

bool Screen::hasFocus() {
  return hasFocus_;
}

} // namespace x2tk
